﻿using CefSharp;
using CefSharp.WinForms;
using CefSharp.SchemeHandler;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp.Handler;
using SuperSocket.WebSocket;
using dianping_shop_comment_collecter.models;
using System.Diagnostics;
using System.IO;
using Newtonsoft.Json;

namespace dianping_shop_comment_collecter
{
    public partial class Form1 : Form
    {
        public static List<worker> workers = new List<worker>();
        WebSocketServer ws;
        Dictionary<int, City> connitues = new Dictionary<int, City>();
        bool assigned = false;
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            InitializeWebSocket();
        }


        void ChangeDataSource()
        {

        }


        void InitializeWebSocket()
        {
            ws = new WebSocketServer();
            ws.NewMessageReceived += Ws_NewMessageReceived; ;//当有信息传入时
            ws.NewSessionConnected += Ws_NewSessionConnected; ;//当有用户连入时
            ws.SessionClosed += Ws_SessionClosed; ;//当有用户退出时
            ws.NewDataReceived += Ws_NewDataReceived; ;//当有数据传入时
            if (ws.Setup(10086))//绑定端口
                ws.Start();//启动服务        
        }

        private void Ws_NewDataReceived(WebSocketSession session, byte[] value)
        {
            Debug.WriteLine("Ws_NewDataReceived:" + Encoding.UTF8.GetString(value));
        }

        private void Ws_SessionClosed(WebSocketSession session, SuperSocket.SocketBase.CloseReason value)
        {
            Debug.WriteLine("Ws_SessionClosed:" + value.ToString());
            var worker = workers.SingleOrDefault(q => q.sesstion_id == session.SessionID);
            worker.online_status = false;
            worker.status = worker_status.died;
            try
            {
                Process.GetProcessById(worker.pid).Kill();
            }
            catch
            {

            }

        }

        private void Ws_NewSessionConnected(WebSocketSession session)
        {
            Debug.WriteLine("Ws_NewSessionConnected:" + session.SessionID);
        }

        private void Ws_NewMessageReceived(WebSocketSession session, string value)
        {
            Debug.WriteLine("Ws_NewMessageReceived:" + value);
            ProcessMssage(Newtonsoft.Json.JsonConvert.DeserializeObject<Common.models.Message>(value), session);
        }
        void ProcessMssage(Common.models.Message message, WebSocketSession session = null)
        {
            switch (message.msgType)
            {
                case Common.constants.MsgType.Connected:
                    var worker = workers.SingleOrDefault(q => q.pid == Convert.ToInt32(message.Data));
                    worker.sesstion_id = session.SessionID;
                    worker.online_status = true;
                    worker.status = worker_status.running;
                    txtLog.AppendText(@" worker:" + worker.pid + " connected succeful!");
                    if (workers.Count(q => q.online_status) == numericUpDown1.Value)
                    { 
                        if (!assigned)
                        {
                            var files = Directory.GetFiles(Path.Combine(Application.StartupPath, "cities")).Where(q => q.Contains("native")).ToList();
                            Dictionary<int, City> cities = new Dictionary<int, City>();
                            var index = 0;
                            foreach (var file in files)
                            {
                                var city = JsonConvert.DeserializeObject<City>(File.ReadAllText(file));
                                cities.Add(index, city);
                                index++;
                            }
                            index = 0;
                            List<WebSocketSession> sessions = new List<WebSocketSession>();
                            foreach (var worker2 in workers)
                            {
                                var session2 = ws.GetSessionByID(worker2.sesstion_id);
                                var msg = new Common.models.Message()
                                {
                                    msgType = Common.constants.MsgType.BeginFetch,
                                    Data = JsonConvert.SerializeObject(cities[index])
                                };
                                session2.Send(JsonConvert.SerializeObject(msg));
                                index++;
                            }
                            assigned = true;
                        }
                        else
                        {
                            var session2 = ws.GetSessionByID(worker.sesstion_id);
                            var msg = new Common.models.Message()
                            {
                                msgType = Common.constants.MsgType.BeginFetch,
                                Data = JsonConvert.SerializeObject(this.connitues[Convert.ToInt32(message.Data)])
                            };
                            session2.Send(JsonConvert.SerializeObject(msg));
                        }

                    }
                    else
                    {
                        if (assigned)
                        {
                            var session2 = ws.GetSessionByID(worker.sesstion_id);
                            var msg = new Common.models.Message()
                            {
                                msgType = Common.constants.MsgType.BeginFetch,
                                Data = JsonConvert.SerializeObject(this.connitues[Convert.ToInt32(message.Data)])
                            };
                            session2.Send(JsonConvert.SerializeObject(msg));
                        }
                    }
                    break;
                case Common.constants.MsgType.Done:
                    break;
                case Common.constants.MsgType.Exit:
                    break;
                case Common.constants.MsgType.Continue:
                    var pid =  forkWorker();
                    connitues.Add(pid, JsonConvert.DeserializeObject<City>(message.Data));
                    break;
                default:
                    break;
            }
            notifal_UI();
        }



        void notifal_UI()
        {
            dataGridView1.DataSource = workers;
        }

        private void btnStartGet_Click(object sender, EventArgs e)
        {
            if (numericUpDown1.Value <= 0)
            {
                MessageBox.Show("请输入一个正确的数字?");
                numericUpDown1.Focus();
                return;
            }
            numericUpDown1.Enabled = false;
            for (int i = 0; i < numericUpDown1.Value; i++)
            {
                forkWorker();
            }

        }

        public static long GetTimeStamp(bool bflag = false)
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            long ret;
            if (bflag)
                ret = Convert.ToInt64(ts.TotalSeconds);
            else
                ret = Convert.ToInt64(ts.TotalMilliseconds);
            return ret;
        }
        int forkWorker()
        {
            var p = new Process();
            p.StartInfo.FileName = Path.Combine(Application.StartupPath, "dianping-shop-comment-collecter-worker.exe"); //"输入完整的路径"
            p.Start();
            workers.Add(new worker()
            {
                pid = p.Id,
                online_status = false,
                status = worker_status.starting,
                up_time = GetTimeStamp()
            });
            txtLog.AppendText("fork worker:" + p.Id + "successful !");
            return p.Id;
        }
    }
}
